#include "makeWorker.h"

int get_current_path(MysqlPool_t *mysqlpool, char *path, int pre_path, char username[])
{
    // 从连接池中获取一个连接
    MYSQL *mysql = mysql_pool_get(mysqlpool);
    if (!mysql)
    {
        LOG_ERROR("无法从连接池中获取MySQL连接");
        return -1;
    }
    // 构建SQL查询语句
    char sql[1024] = {0};

    // 先得到user_id
    int user_id;
    sprintf(sql, "SELECT id FROM users WHERE username = '%s'", username);
    // 执行查询
    if (mysql_query(mysql, sql))
    {
        LOG_ERROR("查询失败: %s", mysql_error(mysql));
        mysql_pool_release(mysqlpool, mysql);
        return -1;
    }
    // 获取查询结果
    MYSQL_RES *result = mysql_store_result(mysql);
    if (result)
    {
        MYSQL_ROW row = mysql_fetch_row(result);
        if (row)
        {
            user_id = atoi(row[0]);
        }
        mysql_free_result(result);
    }

    // 如果pre_path为-1，说明是初次连接，直接返回根目录
    if (pre_path == -1)
    {
        strcpy(path, "/");
        mysql_pool_release(mysqlpool, mysql);
        return 0;
    }
    // 如果pre_path不为-1，说明是其他目录，需要递归查询
    else
    {
        bzero(sql, sizeof(sql));
        snprintf(sql, sizeof(sql),
                 "WITH RECURSIVE path_tree AS (\n"
                 "    -- 起始节点（当前文件/目录）\n"
                 "    SELECT \n"
                 "        id,\n"
                 "        name,\n"
                 "        pre_path,\n"
                 "        name AS full_path\n"
                 "    FROM files\n"
                 "    WHERE pre_path = %d  -- 这里的 d 会被 target_id 替换\n"
                 "\n"
                 "    UNION ALL\n"
                 "\n"
                 "    -- 向上递归追溯 pre_path -> 找上一级目录\n"
                 "    SELECT \n"
                 "        f.id,\n"
                 "        f.name,\n"
                 "        f.pre_path,\n"
                 "        CONCAT(f.name, '/', pt.full_path) AS full_path\n"
                 "    FROM files f\n"
                 "    JOIN path_tree pt ON f.id = pt.pre_path\n"
                 ")\n"
                 "\n"
                 "-- 最终选择结果\n"
                 "SELECT full_path FROM path_tree\n"
                 "WHERE pre_path = -1   -- 表示根目录，这里的 pre_path 是 SQL 表中的列名\n"
                 "LIMIT 1;",
                 pre_path);
        // 执行查询
        if (mysql_query(mysql, sql))
        {
            LOG_ERROR("查询失败: %s", mysql_error(mysql));
            mysql_pool_release(mysqlpool, mysql);
            return -1;
        }
        // 获取查询结果
        MYSQL_RES *result2 = mysql_store_result(mysql);
        if (result2)
        {
            MYSQL_ROW row = mysql_fetch_row(result2);
            if (row)
            {
                strcpy(path, row[0]);
            }
        }
        mysql_free_result(result2);
        mysql_pool_release(mysqlpool, mysql);
        return 0;
    }
}
// 处理ls命令
int deal_ls(int netfd, MysqlPool_t *mysqlpool)
{
    int pre_path = -1;
    train_t train;
    char username[1024] = {0};
    char cur_path[1024] = {0}; // 当前路径

    get_a_session(netfd, pre_path, username);
    LOG_INFO("用户 %s 执行 ls 命令，fd = %d\n", username, netfd);
    get_current_path(mysqlpool, cur_path, pre_path, username); // 获取当前路径
    LOG_INFO("用户 %s 当前路径为 %s\n", username, cur_path);

    // 使用当前路径的id来查询数据库，所有pre_path为当前路径的id的文件的name
    MYSQL *mysql = mysql_pool_get(mysqlpool);
    if (!mysql)
    {
        LOG_ERROR("无法从连接池中获取MySQL连接");
        return -1;
    }
    char sql[1024] = {0};
    snprintf(sql, sizeof(sql),
             "select filename from files where pre_path = %d", pre_path);
    if (mysql_query(mysql, sql))
    {
        LOG_ERROR("查询失败: %s", mysql_error(mysql));
        mysql_pool_release(mysqlpool, mysql);
        return -1;
    }
    // 获取查询结果
    MYSQL_RES *result = mysql_store_result(mysql);
    LOG_INFO("查询成功\n");
    // 存放文件名的数组
    char filename[1024][1024] = {0};
    int num = 0;
    if (result)
    {
        LOG_INFO("get filename start.\n");
        MYSQL_ROW row = {0};
        while ((row = mysql_fetch_row(result)))
        {
            // printf("%s\n", row[0]);
            // 将文件名发送给客户端
            strcpy(filename[num], row[0]);
            LOG_INFO("get filename %s success\n", filename[num]);

            num++;
        }

        bzero(&train, sizeof(train));
        train.train_len = sizeof(num);
        memcpy(train.train_data, &num, sizeof(num));
        send(netfd, &train, sizeof(train.train_len) + sizeof(num), 0);
        LOG_INFO("send num %d success\n", num);
        for (int i = 0; i < num; i++)
        {
            bzero(&train, sizeof(train));
            train.train_len = strlen(filename[i]);
            strcpy(train.train_data, filename[i]);
            send(netfd, &train, sizeof(train.train_len) + train.train_len, 0);
            LOG_INFO("send filename %s to client\n", filename[i]);
        }
        LOG_INFO("ls over. \n");
        mysql_free_result(result);
        mysql_pool_release(mysqlpool, mysql);
        return 0;
    }
    LOG_ERROR("get no filename. \n");
    bzero(&train, sizeof(train));
    train.train_len = sizeof(num);
    memcpy(train.train_data, &num, sizeof(num));
    send(netfd, &train, sizeof(train.train_len) + sizeof(num), 0);
    LOG_INFO("send num %d success\n", num);
    mysql_free_result(result);
    mysql_pool_release(mysqlpool, mysql);
    LOG_INFO("send null to client\n");
    return 0;
}
// 处理quit命令
int deal_quit(int epfd, int netfd, MysqlPool_t *mysql_pool)
{
    LOG_INFO("deal_quit:netfd = %d\n", netfd);
    MYSQL *mysql = mysql_pool_get(mysql_pool);
    LOG_INFO("deal_quit:mysql = %p\n", mysql);
    if (!mysql)
    {
        LOG_ERROR("无法从连接池中获取MySQL连接");
        return -1;
    }
    char sql[1024] = {0};
    // 得到当前的用户名
    char username[1024] = {0};
    int pre_path = -1;
    get_a_session(netfd, pre_path, username);
    // 更新该用户的最后一次登录时间
    snprintf(sql, sizeof(sql),
             "update users set last_login = now() where username = '%s'", username);
    LOG_INFO("updata last_login sql = %s\n", sql);
    if (mysql_query(mysql, sql))
    {
        LOG_ERROR("更新失败: %s", mysql_error(mysql));
        mysql_pool_release(mysql_pool, mysql);
        return -1;
    }
    LOG_INFO("updata last_login success\n");
    // 清除当前用户的资源
    delete_session(netfd);
    LOG_INFO("delete session success\n");
    mysql_pool_release(mysql_pool, mysql);
    LOG_INFO("release mysql success\n");
    LOG_INFO("epfd = %d, netfd = %d\n", epfd, netfd);
    epollDel(epfd, netfd);

    close(netfd);

    LOG_INFO("用户 %s 已退出，FD = %d\n", username, netfd);
    return 0;
}
// 处理put命令
int deal_put(int netfd, char *filename, MysqlPool_t *mysqlpool)
{
    LOG_INFO("deal_put:netfd = %d\n", netfd);

    // 得到当前的用户名
    ssize_t filesize;
    char username[1024] = {0};
    int pre_path = -1;
    get_a_session(netfd, pre_path, username);
    LOG_INFO("deal_put:username = %s\n", username);
    // 得到当前的路径
    char cur_path[1024] = {0};
    get_current_path(mysqlpool, cur_path, pre_path, username);
    LOG_INFO("deal_put:cur_path = %s\n", cur_path);
    // 接收文件哈希值
    char hash[65] = {0};

    train_t train;
    bzero(&train, sizeof(train));
    recv_n(netfd, &train, sizeof(train.train_len));
    recv_n(netfd, train.train_data, train.train_len);
    memcpy(hash, train.train_data, train.train_len);
    LOG_INFO("deal_put:hash = %s\n", hash);
    // 查找当前用户的id
    int user_id;
    MYSQL *mysql = mysql_pool_get(mysqlpool);
    if (!mysql)
    {
        LOG_ERROR("无法从连接池中获取MySQL连接");
        LOG_ERROR("查询失败: %s", mysql_error(mysql));
        mysql_pool_release(mysqlpool, mysql);
        return -1;
    }
    char sql[2048] = {0};
    snprintf(sql, sizeof(sql),
             "select id from users where username = '%s'", username);
    LOG_INFO("deal_put:sql = %s\n", sql);
    if (mysql_query(mysql, sql))
    {
        LOG_ERROR("查询失败: %s", mysql_error(mysql));
        mysql_pool_release(mysqlpool, mysql);
        return -1;
    }
    MYSQL_RES *result = mysql_store_result(mysql);
    if (result)
    {
        MYSQL_ROW row = mysql_fetch_row(result);
        if (row)
        {
            user_id = atoi(row[0]);
            LOG_INFO("deal_put:user_id = %d\n", user_id);
        }
        mysql_free_result(result);
        mysql_pool_release(mysqlpool, mysql);
    }
    // 确定系统中是否存在该文件

    snprintf(sql, sizeof(sql),
             "select * from files where file_hash = '%s'", hash);
    LOG_INFO("deal_put:sql = %s\n", sql);
    mysql = mysql_pool_get(mysqlpool);
    int flag; // 0表示可以发送文件，-1,-2表示不可以发送文件
    if (!mysql)
    {
        LOG_ERROR("无法从连接池中获取MySQL连接");
        LOG_ERROR("查询失败: %s", mysql_error(mysql));
        mysql_pool_release(mysqlpool, mysql);
        // 告诉客户端不用再发送文件，服务端报错了
        flag = -1;
        send(netfd, &flag, sizeof(flag), 0);
        // bzero(&train, sizeof(train));
        // train.train_len = sizeof(flag);
        // memcpy(train.train_data, &flag, sizeof(flag));
        // send(netfd, &train, sizeof(train.train_len) + sizeof(flag), 0);
        LOG_INFO("deal_put:发送文件标志 -1 成功\n");
        return -1;
    }

    if (mysql_query(mysql, sql))
    {
        LOG_ERROR("查询失败: %s", mysql_error(mysql));
        mysql_pool_release(mysqlpool, mysql);
        // 告诉客户端不用再发送文件，服务端报错了
        flag = -1;
        bzero(&train, sizeof(train));
        train.train_len = sizeof(flag);
        memcpy(train.train_data, &flag, sizeof(flag));
        send(netfd, &train, sizeof(train.train_len) + sizeof(flag), 0);
        return -1;
    }
    result = mysql_store_result(mysql);
    if (result)
    {
        // 接收返回数据
        if (mysql_num_rows(result) == 0)
        {
            LOG_INFO("deal_put:文件不存在\n");
            // 告诉客户端可以发送文件
            flag = 0;
            send(netfd, &flag, sizeof(flag), 0);
            // bzero(&train, sizeof(train));
            // train.train_len = sizeof(flag);
            // memcpy(train.train_data, &flag, sizeof(flag));
            // send(netfd, &train, sizeof(train.train_len) + sizeof(flag), 0);
            LOG_INFO("deal_put:发送文件标志成功\n");
            // 接收文件,并以哈希值为名存储
            // 接收文件大小
            bzero(&train, sizeof(train));
            recv_n(netfd, &train, sizeof(train.train_len));
            recv_n(netfd, train.train_data, train.train_len);
            memcpy(&filesize, train.train_data, sizeof(train.train_len));

            LOG_INFO("deal_put:filesize = %ld\n", filesize);
            // char temporary_path[6000] = {0};
            // snprintf(temporary_path, sizeof(temporary_path),
            //          "%s/%s", cur_path, filename);
            recv_file(netfd, hash, filesize);
            // 插入数据库
            snprintf(sql, sizeof(sql),
                     "insert into files(user_id,filename,file_hash,storage_path,pre_path,upload_time,file_num,size) values(%d,'%s','%s','%s',%d,now(),1,%ld)",
                     user_id, filename, hash, cur_path, pre_path, filesize);
            LOG_INFO("deal_put:sql = %s\n", sql);
            if (mysql_query(mysql, sql))
            {
                LOG_ERROR("插入失败: %s", mysql_error(mysql));
                mysql_pool_release(mysqlpool, mysql);
                return -1;
            }
            mysql_free_result(result);
            mysql_pool_release(mysqlpool, mysql);
            return 0;
        }
        LOG_INFO("deal_put:文件已存在\n");
        // 告诉客户端不用再发送文件，服务端有这个文件，可以实现秒传
        flag = 1;
        send(netfd, &flag, sizeof(flag), 0);
        // bzero(&train, sizeof(train));
        // train.train_len = sizeof(flag);
        // memcpy(train.train_data, &flag, sizeof(flag));
        // send(netfd, &train, sizeof(train.train_len) + sizeof(flag), 0);
        LOG_INFO("deal_put:发送文件标志成功\n");
        // 查看本用户当前文件夹中是否存在该文件
        snprintf(sql, sizeof(sql),
                 "select * from files where user_id = %d and file_hash = '%s'",
                 user_id, hash);
        if (mysql_query(mysql, sql))
        {
            LOG_ERROR("查询失败: %s", mysql_error(mysql));
            mysql_pool_release(mysqlpool, mysql);
            return -1;
        }
        MYSQL_RES *result = mysql_store_result(mysql);
        if (result)
        {
            // 接收返回数据
            if (mysql_num_rows(result) == 0)
            {
                LOG_INFO("deal_put:当前文件夹 文件不存在\n");
                // 插入数据库
                snprintf(sql, sizeof(sql),
                         "insert into files(user_id,filename,file_hash,storage_path,pre_path,upload_time,file_num,size) values(%d,'%s','%s','%s',%d,now(),1,%ld)",
                         user_id, filename, hash, cur_path, pre_path, filesize);
                LOG_INFO("deal_put:sql = %s\n", sql);
                if (mysql_query(mysql, sql))
                {
                    LOG_ERROR("插入失败: %s", mysql_error(mysql));
                    mysql_pool_release(mysqlpool, mysql);
                    return -1;
                }

                mysql_free_result(result);
                mysql_pool_release(mysqlpool, mysql);
                return 0;
            }
            else
            {
                LOG_INFO("deal_put:当前文件夹 文件已存在\n");
                // 当前文件＋已经存在该文件，不用上传了，直接返回
                mysql_free_result(result);
                mysql_pool_release(mysqlpool, mysql);
                return 0;
            }
        }
    }

    flag = -2;
    send(netfd, &flag, sizeof(flag), 0);
    // bzero(&train, sizeof(train));
    // train.train_len = sizeof(flag);
    // memcpy(train.train_data, &flag, sizeof(flag));
    // send(netfd, &train, sizeof(train.train_len) + sizeof(flag), 0);
    LOG_ERROR("查询失败: %s", mysql_error(mysql));
    mysql_pool_release(mysqlpool, mysql);
    return -1;
}
